#ifndef ODBC_DETAILS_DATE_BUFFER_BASE_HPP
#define ODBC_DETAILS_DATE_BUFFER_BASE_HPP

#include "odbc/details/buffer_base.hpp"
#include <boost/date_time/gregorian/gregorian.hpp>

namespace odbc { namespace details
{

/// \ingroup odbcpp
/// \brief It provides the common functionality of buffers that map date types.
/// \param OdbcTID the identifier of the ODBC type corresponding to the date type to be mapped to the buffer. 
///		See odbc::odbc_types
/// \param SqlTID the identifier of the SQL type corresponding to the date type to be mapped to the buffer.
///		See odbc::sql_types
template< odbc_types::type_enum OdbcTID, sql_types::type_enum SqlTID>
class date_buffer_base: public buffer_base< OdbcTID, SqlTID>
{
	typedef buffer_base< OdbcTID, SqlTID> MyBaseT_;
public:
	typedef boost::gregorian::date value_type;
	typedef SQL_DATE_STRUCT buffer_type;
	typedef typename MyBaseT_::size_type size_type;

	/// \brief It initializes the buffer and copies the specified value into it.
	/// \param initial_value the value to be copied in the buffer.
	date_buffer_base( const value_type& initial_value)
		: MyBaseT_( sizeof( buffer_type))
	{
	}

	/// \brief It initializes the buffer. The content of the buffer is uninitialized.
	date_buffer_base()
	{
	}

	/// \brief It maps the specified value to the buffer.
	/// \param value the value to be copied to the buffer.
	/// \warning The buffer will copy the data, and not try to hold a reference to the given value to be set.
	void set_value( const value_type& value)
	{
		buffer_.year = value.year();
		buffer_.month = value.month();
		buffer_.day = value.day();
		this->set_length_indicator( sizeof( buffer_type));
	}

	/// \brief It gives the value mapped in the buffer.
	/// \pre The buffer doesn't contain a NULL value.
	value_type value() const
	{
		assert( !this->contains_null());
		return value_type( buffer_.year, buffer_.month, buffer_.day);
	}

	/// \brief It gets the memory address of the buffer.
	/// \details
	///		The buffer address is requested by ODBC API functions and it is not intended for direct use.
	/// \{
	void* buffer_addr() { return static_cast< void*>( &buffer_); }
	const void* buffer_addr() const { return static_cast<const void*>( &buffer_); }
	/// \}

	/// \brief It gets the size of the buffer.
	size_type size() const { return sizeof( buffer_); }

private:
	buffer_type buffer_;
};


}} // namespace details // namespace odbc

#endif // ODBC_DETAILS_DATE_BUFFER_BASE_HPP
